// 基础系统命名空间
using System;
using System.IO;
using System.Net.Http;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Collections.Generic;

// Windows Forms 相关（使用别名）
using WinForms = System.Windows.Forms;

// WPF 相关（使用别名）
using WPF = System.Windows;
using WPFControls = System.Windows.Controls;
using WPFMedia = System.Windows.Media;
using WPFImaging = System.Windows.Media.Imaging;

// 其他第三方库
using Microsoft.Win32;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serilog;
using SocketIOClient;
using SocketIOClient.Transport;
using System.Text.Json;
using System.Text.Json.Nodes;
using STJ = System.Text.Json;

// 项目内部命名空间
using PC.Models;
using PC.Converters;

// 系统绘图相关（使用别名）
using SDIcon = System.Drawing.Icon;
using SDImaging = System.Drawing.Imaging;

namespace PC
{
    public partial class ChatWindow : WPF.Window
    {
        private readonly string _baseUrl = "http://localhost:3003";
        private readonly ILogger _logger;
        private readonly HttpClient _httpClient;
        private readonly SocketIOClient.SocketIO _socket;
        private readonly ChatUser _currentUser;
        private ChatUser? _selectedUser;
        private bool _isGroupChat = true;
        private bool _isClosing = false;

        public ObservableCollection<ChatUser> Users { get; } = new();
        public ObservableCollection<ChatMessage> Messages { get; } = new();

        public ChatWindow(UserInfo userInfo)
        {
            if (userInfo == null)
            {
                throw new ArgumentNullException(nameof(userInfo), "用户信息不能为空");
            }
            if (string.IsNullOrEmpty(userInfo.Username))
            {
                throw new ArgumentException("用户名不能为空", nameof(userInfo));
            }

            // 初始化基本服务
            _logger = Log.Logger;
            _httpClient = new HttpClient();
            _currentUser = new ChatUser
            {
                Username = userInfo.Username,
                Status = string.IsNullOrEmpty(userInfo.Status) ? "online" : userInfo.Status,
                UserId = userInfo.UserId
            };

            _logger.Information("=== 初始化聊天窗口 ===");
            _logger.Information("当前用户: {@CurrentUser}", _currentUser);

            // 初始化 Socket.IO
            _socket = new SocketIOClient.SocketIO(_baseUrl, new SocketIOOptions
            {
                Transport = TransportProtocol.WebSocket,
                Reconnection = true,
                ReconnectionDelay = 1000,
                ReconnectionAttempts = 3,
                Path = "/socket.io/",
                ConnectionTimeout = TimeSpan.FromSeconds(5)
            });

            // 初始化窗口组件
            InitializeComponent();
            DataContext = this;

            // 设置当前用户信息
            CurrentUserText.Text = $"当前用户：{_currentUser.Username}";
            StatusComboBox.SelectedIndex = _currentUser.Status switch
            {
                "online" => 0,
                "away" => 1,
                "offline" => 2,
                _ => 0
            };

            // 设置数据源
            UserListBox.ItemsSource = Users;
            MessageList.ItemsSource = Messages;

            // 初始化 Socket.IO 事件处理
            InitializeSocketEvents();

            // 在新线程中连接到服务器
            Task.Run(async () => await ConnectToServerAsync());

            // 注册窗口关闭事件
            this.Closing += ChatWindow_Closing;
        }

        private async Task ConnectToServerAsync()
        {
            try
            {
                await _socket.ConnectAsync();
                _logger.Information("[连接] 成功连接到聊天服务器");

                await _socket.EmitAsync("user_join", _currentUser.Username);
                await _socket.EmitAsync("get_online_users");
                await _socket.EmitAsync("get_history"); // 获取历史消息
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "连接服务器失败");
                WPF.MessageBox.Show("连接服务器失败：" + ex.Message, "错误", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Error);
            }
        }

        private void ChatWindow_Closing(object? sender, CancelEventArgs e)
        {
            try
            {
                _logger.Information("正在关闭聊天窗口");
                if (_socket != null && _socket.Connected)
                {
                    _socket.DisconnectAsync().Wait();
                    _logger.Information("已断开与服务器的连接");
                }
                WPF.Application.Current.Shutdown();
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "关闭窗口时发生错误");
            }
        }

        // 处理消息框的键盘输入事件
        private async void MessageTextBox_KeyDown(object sender, WPF.Input.KeyEventArgs e)
        {
            if (e.Key == WPF.Input.Key.Enter)
            {
                await SendMessage();
                e.Handled = true;
            }
        }

        // 处理状态下拉框变化事件
        private async void StatusComboBox_SelectionChanged(object sender, WPFControls.SelectionChangedEventArgs e)
        {
            if (!_socket.Connected)
            {
                _logger.Warning("[状态] 无法更新状态：未连接到服务器");
                return;
            }

            try
            {
                if (StatusComboBox.SelectedItem is WPFControls.ComboBoxItem item && item.Tag != null)
                {
                    var status = item.Tag.ToString();
                    if (!string.IsNullOrEmpty(status))
                    {
                        _logger.Debug("[状态] 更新状态为: {Status}", status);
                        await _socket.EmitAsync("update_status", status);
                        _currentUser.Status = status;
                    }
                    else
                    {
                        _logger.Warning("[状态] 无法更新状态：状态值为空");
                    }
                }
                else
                {
                    _logger.Warning("[状态] 无法更新状态：未选择有效的状态选项");
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "[状态] 更新状态失败");
                WPF.MessageBox.Show("更新状态失败：" + ex.Message, "错误", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Error);
            }
        }

        // 处理群聊按钮点击事件
        private void GroupChatButton_Click(object sender, WPF.RoutedEventArgs e)
        {
            _selectedUser = null;
            _isGroupChat = true;
            ChatTitleText.Text = "群聊";
            UserListBox.SelectedItem = null;
        }

        // 处理用户列表选择变化事件
        private void UserListBox_SelectionChanged(object sender, WPFControls.SelectionChangedEventArgs e)
        {
            var selectedUser = UserListBox.SelectedItem as ChatUser;
            if (selectedUser != null)
            {
                _selectedUser = selectedUser;
                _isGroupChat = false;
                ChatTitleText.Text = $"与 {selectedUser.Username} 私聊中";
            }
        }

        // 处理发送消息
        private async Task SendMessage()
        {
            var message = MessageTextBox.Text.Trim();
            if (string.IsNullOrEmpty(message)) return;

            try
            {
                if (!_socket.Connected)
                {
                    WPF.MessageBox.Show("未连接到服务器，请检查网络连接", "错误", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Error);
                    return;
                }

                // 发送消息到服务器
                if (_isGroupChat)
                {
                    var data = new { message };
                    _logger.Debug("[发送] 发送群聊消息: {@MessageData}", data);
                    await _socket.EmitAsync("chat_message", data);
                }
                else if (_selectedUser != null && !string.IsNullOrEmpty(_selectedUser.UserId))
                {
                    var data = new { to = _selectedUser.UserId, message };
                    _logger.Debug("[发送] 发送私聊消息: {@MessageData}", data);
                    await _socket.EmitAsync("private_message", data);
                }
                else
                {
                    _logger.Warning("[发送] 无法发送私聊消息：接收者ID为空");
                    WPF.MessageBox.Show("无法发送私聊消息：接收者信息无效", "错误", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Error);
                    return;
                }

                MessageTextBox.Clear(); // 清空输入框
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "[发送] 发送消息失败");
                WPF.MessageBox.Show("发送消息失败：" + ex.Message, "错误", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Error);
            }
        }

        // 处理文件发送
        private async void SendFileButton_Click(object sender, WPF.RoutedEventArgs e)
        {
            var openFileDialog = new Microsoft.Win32.OpenFileDialog();
            if (openFileDialog.ShowDialog() == true)
            {
                try
                {
                    var fileInfo = new FileInfo(openFileDialog.FileName);
                    _logger.Debug("[文件] 文件信息: 名称={Name}, 大小={Size}字节", fileInfo.Name, fileInfo.Length);

                    var content = new MultipartFormDataContent();
                    var fileContent = new StreamContent(File.OpenRead(openFileDialog.FileName));
                    fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
                    content.Add(fileContent, "file", fileInfo.Name);
                    
                    // 添加上传者信息
                    content.Add(new StringContent(_currentUser.Username), "uploadedBy[username]");
                    content.Add(new StringContent(_currentUser.UserId), "uploadedBy[userId]");

                    _logger.Debug("[文件] 请求头: {@Headers}", content.Headers);
                    var response = await _httpClient.PostAsync($"{_baseUrl}/upload", content);
                    var responseContent = await response.Content.ReadAsStringAsync();
                    _logger.Debug("[文件] 上传响应: 状态码=\"{Status}\", 内容={Content}", response.StatusCode, responseContent);

                    if (response.IsSuccessStatusCode)
                    {
                        var uploadedFile = STJ.JsonSerializer.Deserialize<ChatFileInfo>(responseContent);
                        _logger.Information("[文件] 上传成功: {@FileInfo}", uploadedFile);

                        // 发送文件消息
                        if (_isGroupChat)
                        {
                            var data = new { 
                                type = "group",
                                from = new {
                                    userId = _currentUser.UserId,
                                    username = _currentUser.Username
                                },
                                file = new {
                                    filename = uploadedFile.Filename,
                                    originalname = uploadedFile.OriginalName,
                                    mimetype = "application/octet-stream",
                                    size = uploadedFile.Size
                                }
                            };
                            _logger.Debug("[文件] 发送群聊文件消息: {@MessageData}", data);
                            await _socket.EmitAsync("chat_message", data);
                        }
                        else if (_selectedUser != null)
                        {
                            var data = new { 
                                type = "private",
                                to = _selectedUser.UserId,
                                from = new {
                                    userId = _currentUser.UserId,
                                    username = _currentUser.Username
                                },
                                file = new {
                                    filename = uploadedFile.Filename,
                                    originalname = uploadedFile.OriginalName,
                                    mimetype = "application/octet-stream",
                                    size = uploadedFile.Size
                                }
                            };
                            _logger.Debug("[文件] 发送私聊文件消息: {@MessageData}", data);
                            await _socket.EmitAsync("private_message", data);
                        }
                    }
                    else
                    {
                        throw new Exception($"上传失败：{response.StatusCode}");
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[文件] 发送文件失败");
                    WPF.MessageBox.Show("发送文件失败：" + ex.Message, "错误", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Error);
                }
            }
        }

        // 初始化 Socket.IO 事件处理
        private void InitializeSocketEvents()
        {
            _socket.OnConnected += (sender, e) =>
            {
                _logger.Information("[事件] 已连接到聊天服务器");
            };

            _socket.OnDisconnected += (sender, e) =>
            {
                _logger.Warning("与聊天服务器断开连接");
            };

            // 在线用户列表
            _socket.On("online_users", async response =>
            {
                try
                {
                    _logger.Debug("[事件] 请求在线用户列表");
                    var users = response.GetValue<List<ChatUser>>();
                    if (users == null)
                    {
                        _logger.Warning("[事件] 收到无效的用户列表");
                        return;
                    }

                    await Dispatcher.InvokeAsync(() =>
                    {
                        Users.Clear();
                        foreach (var user in users.Where(u => u.Username != _currentUser.Username))
                        {
                            Users.Add(user);
                        }
                    });
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[事件] 处理在线用户列表失败");
                }
            });

            // 新消息
            _socket.On("chat_message", async response =>
            {
                try
                {
                    var data = response.GetValue<JsonElement>();
                    _logger.Debug("[消息] 收到新消息: {@Data}", data);
                    await HandleMessage(data, false);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[消息] 处理新消息失败");
                }
            });

            // 私聊消息
            _socket.On("private_message", async response =>
            {
                try
                {
                    var data = response.GetValue<JsonElement>();
                    _logger.Debug("[消息] 收到私聊消息: {@Data}", data);
                    await HandleMessage(data, true);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[消息] 处理私聊消息失败");
                }
            });

            // 用户加入
            _socket.On("user_joined", async response =>
            {
                try
                {
                    _logger.Debug("[事件] 用户加入事件");
                    await _socket.EmitAsync("get_online_users");
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[事件] 处理用户加入事件失败");
                }
            });

            // 用户离开
            _socket.On("user_left", async response =>
            {
                try
                {
                    _logger.Debug("[事件] 用户离开事件");
                    await _socket.EmitAsync("get_online_users");
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[事件] 处理用户离开事件失败");
                }
            });

            // 用户状态更新
            _socket.On("user_status_updated", async response =>
            {
                try
                {
                    _logger.Debug("[事件] 用户状态更新事件");
                    await _socket.EmitAsync("get_online_users");
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[事件] 处理用户状态更新事件失败");
                }
            });

            // 历史消息
            _socket.On("message_history", async response =>
            {
                try
                {
                    var messages = response.GetValue<JsonElement>();
                    _logger.Debug("[消息] 收到历史消息原始数据: {RawData}", messages.GetRawText());
                    
                    if (messages.ValueKind == JsonValueKind.Array)
                    {
                        foreach (var message in messages.EnumerateArray())
                        {
                            _logger.Debug("[消息] 处理历史消息项: {RawData}", message.GetRawText());
                            await HandleMessage(message, message.TryGetProperty("Type", out var type) && type.GetString() == "private");
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "[消息] 处理历史消息失败");
                }
            });
        }

        // 处理发送按钮点击事件
        private async void SendButton_Click(object sender, WPF.RoutedEventArgs e)
        {
            await SendMessage();
        }

        // 用户信息类
        public class UserInfo
        {
            public string Username { get; set; } = string.Empty;
            public string Status { get; set; } = "online";
            public string UserId { get; set; } = string.Empty;
        }

        public class ChatUser
        {
            public string UserId { get; set; } = string.Empty;
            public string Username { get; set; } = string.Empty;
            public string Status { get; set; } = string.Empty; // "online", "away", "offline"
        }

        public class ChatMessage
        {
            public string Content { get; set; } = string.Empty;
            public string SenderName { get; set; } = string.Empty;
            private DateTime _timestamp;
            public string Timestamp 
            { 
                get => _timestamp.ToString("yyyy-MM-dd HH:mm:ss");
                set => _timestamp = DateTime.Parse(value);
            }
            public string DisplayTime
            {
                get
                {
                    if (_timestamp.Date == DateTime.Today)
                    {
                        return _timestamp.ToString("HH:mm:ss");
                    }
                    return _timestamp.ToString("yyyy-MM-dd HH:mm:ss");
                }
            }
            public bool IsPrivate { get; set; }
            public bool IsSystemMessage => SenderName == "System";
            public WPF.HorizontalAlignment Alignment { get; set; }
            public WPFMedia.Brush Background { get; set; } = new WPFMedia.SolidColorBrush(WPFMedia.Colors.Transparent);
            public ChatFileInfo? FileInfo { get; set; }
            public WPF.Input.ICommand? DownloadCommand { get; set; }
            public WPFMedia.ImageSource? FileIcon 
            { 
                get
                {
                    if (FileInfo == null) return null;
                    return GetFileIcon(FileInfo.OriginalName);
                }
            }
        }

        public class ChatFileInfo
        {
            [JsonProperty("fileId")]
            public string FileId { get; set; } = string.Empty;

            [JsonProperty("filename")]
            public string Filename { get; set; } = string.Empty;

            [JsonProperty("originalname")]
            public string OriginalName { get; set; } = string.Empty;

            [JsonProperty("url")]
            public string Url { get; set; } = string.Empty;

            [JsonProperty("mimetype")]
            public string MimeType { get; set; } = string.Empty;

            [JsonProperty("size")]
            public long Size { get; set; }
        }

        // 处理文件下载
        private async Task DownloadFile(ChatFileInfo fileInfo)
        {
            try
            {
                var saveFileDialog = new Microsoft.Win32.SaveFileDialog
                {
                    FileName = fileInfo.OriginalName,
                    Title = "保存文件"
                };

                if (saveFileDialog.ShowDialog() == true)
                {
                    var downloadUrl = $"{_baseUrl}/upload/{fileInfo.Filename}";
                    _logger.Debug("[文件] 开始下载文件: {Url}", downloadUrl);

                    var request = new HttpRequestMessage(HttpMethod.Get, downloadUrl);
                    request.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/octet-stream"));

                    var response = await _httpClient.SendAsync(request);
                    if (response.IsSuccessStatusCode)
                    {
                        using var fileStream = File.Create(saveFileDialog.FileName);
                        await response.Content.CopyToAsync(fileStream);
                        _logger.Information("[文件] 文件下载成功: {FilePath}", saveFileDialog.FileName);
                        WPF.MessageBox.Show("文件下载成功！", "提示", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Information);
                    }
                    else
                    {
                        var errorContent = await response.Content.ReadAsStringAsync();
                        throw new Exception($"下载失败：{response.StatusCode}\n{errorContent}");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "[文件] 下载文件失败");
                WPF.MessageBox.Show("下载文件失败：" + ex.Message, "错误", WPF.MessageBoxButton.OK, WPF.MessageBoxImage.Error);
            }
        }

        // 修改消息处理方法，使用正确的解析方式
        private async Task HandleMessage(JsonElement data, bool isPrivate)
        {
            try
            {
                _logger.Debug("[消息] 原始数据: {RawData}", data.GetRawText());
                
                string? username = null;
                string? message = null;
                DateTime timestamp = DateTime.Now;
                ChatFileInfo? fileInfo = null;

                // 尝试按历史消息格式解析
                if (data.TryGetProperty("from", out var fromObj))
                {
                    username = fromObj.TryGetProperty("username", out var usernameElement) ? 
                        usernameElement.GetString() : null;
                }

                // 检查文件信息
                if (data.TryGetProperty("file", out var fileElement))
                {
                    var options = new STJ.JsonSerializerOptions
                    {
                        PropertyNameCaseInsensitive = true
                    };
                    fileInfo = STJ.JsonSerializer.Deserialize<ChatFileInfo>(fileElement.GetRawText(), options);
                    // 如果是文件消息，不再添加文本提示
                    message = string.Empty;
                }
                else if (data.TryGetProperty("content", out var contentElement))
                {
                    message = contentElement.GetString();
                }

                if (data.TryGetProperty("createdAt", out var timeElement) || 
                    data.TryGetProperty("timestamp", out timeElement))
                {
                    if (timeElement.TryGetDateTime(out var parsedTime))
                    {
                        timestamp = parsedTime;
                    }
                }

                if (string.IsNullOrEmpty(message) && fileInfo == null)
                {
                    _logger.Warning("[消息] 消息内容为空且没有文件信息: {RawData}", data.GetRawText());
                    return;
                }

                await Dispatcher.InvokeAsync(() =>
                {
                    var chatMessage = new ChatMessage
                    {
                        Content = message,
                        SenderName = username ?? _currentUser.Username,
                        Timestamp = timestamp.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"),
                        IsPrivate = isPrivate,
                        Alignment = (username ?? _currentUser.Username) == _currentUser.Username ? 
                            WPF.HorizontalAlignment.Right : WPF.HorizontalAlignment.Left,
                        Background = (username ?? _currentUser.Username) == _currentUser.Username ? 
                            new WPFMedia.SolidColorBrush(WPFMedia.Colors.LightBlue) : new WPFMedia.SolidColorBrush(WPFMedia.Colors.LightGray),
                        FileInfo = fileInfo
                    };

                    if (fileInfo != null)
                    {
                        chatMessage.DownloadCommand = new RelayCommand(async () => await DownloadFile(fileInfo));
                    }
                    
                    Messages.Add(chatMessage);
                    MessageScrollViewer.ScrollToBottom();
                });
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "[消息] 处理失败: {RawData}", data.GetRawText());
            }
        }

        // 添加RelayCommand类
        public class RelayCommand : System.Windows.Input.ICommand
        {
            private readonly Func<Task> _execute;

            public RelayCommand(Func<Task> execute)
            {
                _execute = execute;
            }

            public event EventHandler? CanExecuteChanged;

            public bool CanExecute(object? parameter) => true;

            public async void Execute(object? parameter)
            {
                await _execute();
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            if (!_isClosing)
            {
                e.Cancel = true;
                _isClosing = true;
                
                // 先隐藏窗口
                this.Hide();
                
                // 在后台处理清理工作
                Task.Run(async () =>
                {
                    try 
                    {
                        _logger.Information("=== 正在关闭聊天窗口 ===");
                        
                        // 断开 Socket 连接
                        if (_socket != null)
                        {
                            _logger.Debug("正在断开 Socket 连接...");
                            await _socket.DisconnectAsync();
                            _socket.Dispose();
                            _logger.Debug("Socket 连接已断开");
                        }

                        // 释放其他资源
                        _httpClient?.Dispose();
                        
                        // 刷新日志
                        _logger.Information("=== 聊天窗口已关闭 ===");
                        Log.CloseAndFlush();

                        // 在主线程中关闭程序
                        await Dispatcher.InvokeAsync(() =>
                        {
                            WPF.Application.Current.Shutdown();
                        });
                    }
                    catch (Exception ex)
                    {
                        _logger.Error(ex, "关闭窗口时发生错误");
                        Environment.Exit(1);
                    }
                });
            }
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
        }

        private static WPFMedia.ImageSource? GetFileIcon(string fileName)
        {
            try
            {
                var extension = Path.GetExtension(fileName).ToLower();
                var tempFile = Path.Combine(Path.GetTempPath(), $"temp{extension}");
                if (!File.Exists(tempFile))
                {
                    File.WriteAllText(tempFile, string.Empty);
                }

                using var icon = SDIcon.ExtractAssociatedIcon(tempFile);
                if (icon != null)
                {
                    using var bitmap = icon.ToBitmap();
                    using var stream = new MemoryStream();
                    bitmap.Save(stream, SDImaging.ImageFormat.Png);
                    stream.Position = 0;

                    var bitmapImage = new WPFImaging.BitmapImage();
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource = stream;
                    bitmapImage.CacheOption = WPFImaging.BitmapCacheOption.OnLoad;
                    bitmapImage.EndInit();
                    bitmapImage.Freeze();

                    return bitmapImage;
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Warning(ex, "获取文件图标失败");
            }
            return null;
        }
    }
}